<?php

namespace AliyunFinancialGradeIdVerification;


use AlibabaCloud\SDK\Cloudauth\V20190307\Cloudauth;
use AlibabaCloud\SDK\Cloudauth\V20190307\Models\DescribeFaceVerifyRequest;
use AlibabaCloud\SDK\Cloudauth\V20190307\Models\InitFaceVerifyRequest;
use AlibabaCloud\Tea\Exception\TeaError;
use AlibabaCloud\Tea\Utils\Utils;
use AlibabaCloud\Tea\Utils\Utils\RuntimeOptions;
use Darabonba\OpenApi\Models\Config;


/**
 * 阿里云金融级实人认证
 * Class ContrastFaceVerify
 * @package AliyunFinancialGradeIdVerification
 */
class ContrastFaceVerify
{
    private $accessKeyId;
    private $accessKeySecret;
    private $sceneId;
    private $callbackUrl;

    /**
     * 初始化方法
     * ContrastFaceVerify constructor.
     * @param array $config
     */
    public function __construct($config = [])
    {
        $this->accessKeyId = $config['accessKeyId'];
        $this->accessKeySecret = $config['accessKeySecret'];
        $this->sceneId = $config['sceneId'];
        $this->callbackUrl = $config['callbackUrl'];
    }

    /**
     * 获取实人认证唯一标识
     * @param string $metaInfo 环境参数，需要通过客户端SDK获取
     * @param string $realName 真实姓名
     * @param string $idCard 身份证号
     * @return mixed
     * @throws \Exception
     */
    public function getCertifyId($metaInfo = '', $realName = '', $idCard = '')
    {
        $metaInfo = str_ireplace('&quot;', '"', $metaInfo);
        $outerOrderNo = self::getOuterOrderNo(32);
        $args = [
            'outerOrderNo' => $outerOrderNo,
            'certName' => $realName,
            'certNo' => $idCard,
            'metaInfo' => $metaInfo,
        ];
        $return = $this->initialization($args);
        if ($return->body->code != 200) {
            throw new \Exception($return->body->message);
        }
        $certifyId = $return->body->resultObject->certifyId;
        return $certifyId;
    }


    /**
     * 认证结果异步通知地址
     * @param string $certifyId 实人认证唯一标识
     * @return bool
     * @throws \Exception
     */
    public function callbackVerify($certifyId = '')
    {
        $args = [
            'certifyId' => $certifyId,
        ];
        $return = $this->authenticationQuery($args);
        if ($return->body->code == 200) {
            if ($return->body->resultObject->passed == 'T' && $return->body->resultObject->subCode == 200) {//验证通过
                return true;
            } else {//验证失败
                return false;
            }
        }
        throw new \Exception($return->body->message);
    }

    /**
     * 初始化 Client
     * @param string[] $args
     * @return void
     * @throws \Exception
     */
    private function initialization($args)
    {
        // 初始化 Client，采用 AK&SK 鉴权访问的方式，此方式可能会存在泄漏风险，建议使用 STS 方式。
        // 鉴权访问方式请参考：https://help.aliyun.com/document_detail/311677.html
        // 获取 AK 链接：https://usercenter.console.aliyun.com
        $client = self::createClient($this->accessKeyId, $this->accessKeySecret);
        $args['sceneId'] = $this->sceneId;
        $args['productCode'] = "ID_PRO";
        $args['certType'] = "IDENTITY_CARD";
        $args['callbackUrl'] = $this->callbackUrl;
        $initFaceVerifyRequest = new InitFaceVerifyRequest($args);
        $runtime = new RuntimeOptions([]);
        try {
            // 复制代码运行请自行打印 API 的返回值
            $return = $client->initFaceVerifyWithOptions($initFaceVerifyRequest, $runtime);
            return $return;
        } catch (\Exception $error) {
            if (!($error instanceof TeaError)) {
                $error = new TeaError([], $error->getMessage(), $error->getCode(), $error);
            }
            throw new \Exception($error->message);
        }
    }

    private function authenticationQuery($args)
    {
        $client = self::createClient($this->accessKeyId, $this->accessKeySecret);
        $args['sceneId'] = $this->sceneId;
        $describeFaceVerifyRequest = new DescribeFaceVerifyRequest($args);
        $runtime = new RuntimeOptions([]);
        try {
            // 复制代码运行请自行打印 API 的返回值
            $return = $client->describeFaceVerifyWithOptions($describeFaceVerifyRequest, $runtime);
            return $return;
        } catch (\Exception $error) {
            if (!($error instanceof TeaError)) {
                $error = new TeaError([], $error->getMessage(), $error->getCode(), $error);
            }
            // 如有需要，请打印 error
            throw new \Exception($error->message);
        }
    }

    /**
     * 使用AK&SK初始化账号Client
     * @param string $accessKeyId
     * @param string $accessKeySecret
     * @return Cloudauth Client
     */
    private static function createClient($accessKeyId, $accessKeySecret)
    {
        $config = new Config([
            // 必填，您的 AccessKey ID
            "accessKeyId" => $accessKeyId,
            // 必填，您的 AccessKey Secret
            "accessKeySecret" => $accessKeySecret
        ]);
        // 访问的域名
        $config->endpoint = "cloudauth.aliyuncs.com";
        return new Cloudauth($config);
    }

    /**
     * 商户请求唯一标识
     * @param int $length 长度
     * @param string $default 前缀
     * @return string
     */
    private static function getOuterOrderNo($length = 32, $default = '')
    {
        $length -= mb_strlen($default);
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $str = '';
        for ($i = 0; $i < $length; $i++) {
            $str .= $chars[mt_rand(0, strlen($chars) - 1)];
        }
        $str = $default . $str;
        return $str;
    }

}